package baidu;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.Map.Entry;
/**
 * HTTP�������
 * 
 * @author YYmmiinngg
 */
public class HttpRequester {
	public static final String baidu = "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh_CN) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/18.0 BIDUBrowser/2.x Safari/534.7";
	public static final String IPhone = "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16";
	public static final String Android = "Mozilla/5.0 (Linux;U;Android 2.2.1;zh-cn;I7500 Build FRG83) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 Mobile Safari/533.1";
	public static final String IPad = "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10";
	public static final String Navigator = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080219 Firefox/2.0.0.12 Navigator/9.0.0.6";
	public static final String Maxthon = "Mozilla/5.0 (compatible; U) AppleWebKit/533.1 (KHTML, like Gecko) Maxthon/3.0.8.2 Safari/533.1";
	public static final String Opera = "Opera/9.80 (compatible; U) Presto/2.7.39 Version/11.00";
	public static final String Safari = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_7) AppleWebKit/534.16+ (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4";
	public static final String Firefox = "Mozilla/5.0 (compatible; rv:2.0) Gecko/20110101 Firefox/4.0";
	public static final String Chrome = "Mozilla/5.0 (compatible) AppleWebKit/534.21 (KHTML, like Gecko) Chrome/11.0.682.0 Safari/534.21";
	public static final String IE9 = "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)";
	public static final String IE8 = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)";
	public static final String IE7 = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)";
	public static final String IE6 = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
	private Map<String, String> cookieMap = new HashMap<String, String>();
	private boolean log = false;
	private String mod = baidu;
	private void printlog(String str) {
		if (log) {
			System.out.println(str);
		}
	}
	public void setLog(boolean log) {
		this.log = log;
	}
	public void setMod(String mod) {
		this.mod = mod;
	}
	public void setCookie(String cookie) {
		cookie = cookie.trim();
		int end = cookie.indexOf(";");
		int start = 0;
		while (end > 0) {
			String str = cookie.substring(start, end);
			int index = str.indexOf('=');
			String key = str.substring(0, index).trim();
			String value = str.substring(index + 1).trim();
			printlog("SetCookie,key:" + key + ",value:" + value);
			cookieMap.put(key, value);
			start = end + 1;
			end = cookie.indexOf(";", end + 1);
		}
		if (start < cookie.length()) {
			String str = cookie.substring(start, cookie.length());
			int index = str.indexOf('=');
			String key = str.substring(0, index).trim();
			String value = str.substring(index + 1).trim();
			printlog("SetCookie,key:" + key + ",value:" + value);
			cookieMap.put(key, value);
		}
	}
	public String getCookie() {
		StringBuffer sb = new StringBuffer();
		if (cookieMap.size() == 0) {
			return "";
		}
		cookieMap.remove("path");
		for (Entry<String, String> en : cookieMap.entrySet()) {
			sb.append(en.getKey() + "=" + en.getValue() + "; ");
		}
		String re = sb.substring(0, sb.length() - 2);
		printlog("getCookie:" + re);
		return re;
	}
	private Map<String, String> getDefaultPropertyMap() {
		Map<String, String> propertyMap = new HashMap<String, String>();
		propertyMap.put("User-Agent", mod);
		propertyMap.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
		propertyMap.put("Accept-Charset", "GBK,utf-8;q=0.7,*;q=0.3");
		propertyMap.put("Accept-Language", "zh-CN,zh;q=0.8");
		propertyMap.put("Cache-Control", "max-age=0");
		// propertyMap.put("Connection","keep-alive");
		// propertyMap.put("User-Agent", "");
		// propertyMap.put("User-Agent", "");
		return propertyMap;
	}
	private String defaultContentEncoding;
	public HttpRequester() {
		this.defaultContentEncoding = Charset.defaultCharset().name();
	}
	/**
	 * 发送GET请求
	 * 
	 * @param urlString
	 *            URL地址
	 * @return 响应对象
	 * @throws IOException
	 */
	public HttpRespons sendGet(String urlString) throws IOException {
		return this.send(urlString, "GET", null, null);
	}
	/**
	 * 发送GET请求
	 * 
	 * @param urlString
	 *            URL地址
	 * @param params
	 *            参数集合
	 * @return 响应对象
	 * @throws IOException
	 */
	public HttpRespons sendGet(String urlString, Map<String, String> params) throws IOException {
		return this.send(urlString, "GET", params, null);
	}
	/**
	 * 发送GET请求
	 * 
	 * @param urlString
	 *            URL地址
	 * @param params
	 *            参数集合
	 * @param propertys
	 *            请求属性
	 * @return 响应对象
	 * @throws IOException
	 */
	public HttpRespons sendGet(String urlString, Map<String, String> params, Map<String, String> propertys) throws IOException {
		return this.send(urlString, "GET", params, propertys);
	}
	/**
	 * 发送POST请求
	 * 
	 * @param urlString
	 *            URL地址
	 * @return 响应对象
	 * @throws IOException
	 */
	public HttpRespons sendPost(String urlString) throws IOException {
		return this.send(urlString, "POST", null, null);
	}
	/**
	 * 发送POST请求
	 * 
	 * @param urlString
	 *            URL地址
	 * @param params
	 *            参数集合
	 * @return 响应对象
	 * @throws IOException
	 */
	public HttpRespons sendPost(String urlString, Map<String, String> params) throws IOException {
		return this.send(urlString, "POST", params, this.getDefaultPropertyMap());
	}
	/**
	 * 发送POST请求
	 * 
	 * @param urlString
	 *            URL地址
	 * @param params
	 *            参数集合
	 * @param propertys
	 *            请求属性
	 * @return 响应对象
	 * @throws IOException
	 */
	public HttpRespons sendPost(String urlString, Map<String, String> params, Map<String, String> propertys) throws IOException {
		return this.send(urlString, "POST", params, propertys);
	}
	/**
	 * 发送HTTP请求
	 * 
	 * @param urlString
	 * @return 响映对象
	 * @throws IOException
	 */
	private HttpRespons send(String urlString, String method, Map<String, String> parameters, Map<String, String> propertys)
			throws IOException {
		HttpURLConnection urlConnection = null;
		if (!urlString.matches("(?i)^https?://.*")) {
			urlString = "http://" + urlString;
		}
		printlog(urlString);
		if (method.equalsIgnoreCase("GET") && parameters != null) {
			StringBuffer param = new StringBuffer();
			int i = 0;
			for (String key : parameters.keySet()) {
				if (i == 0)
					param.append("?");
				else
					param.append("&");
				param.append(key).append("=").append(parameters.get(key));
				i++;
			}
			urlString += param;
		}
		URL url = new URL(urlString);
		urlConnection = (HttpURLConnection) url.openConnection();
		urlConnection.setRequestMethod(method);
		urlConnection.setDoOutput(true);
		urlConnection.setDoInput(true);
		urlConnection.setUseCaches(true);
		urlConnection.setRequestProperty("Cookie", this.getCookie());
		if (propertys == null) {
			propertys = this.getDefaultPropertyMap();
		}
		for (String key : propertys.keySet()) {
			urlConnection.addRequestProperty(key, propertys.get(key));
		}
		if (method.equalsIgnoreCase("POST") && parameters != null) {
			StringBuffer param = new StringBuffer();
			int i = 0;
			for (String key : parameters.keySet()) {
				if (i != 0)
					param.append("&");
				param.append(key).append("=").append(URLEncoder.encode(parameters.get(key), "UTF-8"));
				i++;
			}
			System.out.println(param);
			byte[] postdata = param.toString().getBytes("utf-8");
			urlConnection.setRequestProperty("Content-Length", String.valueOf(postdata.length));
			urlConnection.getOutputStream().write(postdata);
			urlConnection.getOutputStream().flush();
			urlConnection.getOutputStream().close();
		}
		return this.makeContent(urlString, urlConnection);
	}
	/**
	 * 得到响应对象
	 * 
	 * @param urlConnection
	 * @return 响应对象
	 * @throws IOException
	 */
	private HttpRespons makeContent(String urlString, HttpURLConnection urlConnection) throws IOException {
		HttpRespons httpResponser = new HttpRespons();
		try {
			InputStream in = urlConnection.getInputStream();
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			httpResponser.contentCollection = new Vector<String>();
			byte[] buffer = new byte[1024 * 10];
			int total = 0;
			while ((total = in.read(buffer)) != -1) {
				bos.write(buffer, 0, total);
			}
			Map<String, List<String>> headers = urlConnection.getHeaderFields();
			List<String> cookies = headers.get("Set-Cookie");
			if (cookies != null && cookies.size() > 0)
				for (String s : cookies) {
					this.setCookie(s);
				}
			String ecod = urlConnection.getContentEncoding();
			if (ecod == null)
				ecod = "utf-8";
			httpResponser.urlString = urlString;
			httpResponser.defaultPort = urlConnection.getURL().getDefaultPort();
			httpResponser.file = urlConnection.getURL().getFile();
			httpResponser.host = urlConnection.getURL().getHost();
			httpResponser.path = urlConnection.getURL().getPath();
			httpResponser.port = urlConnection.getURL().getPort();
			httpResponser.protocol = urlConnection.getURL().getProtocol();
			httpResponser.query = urlConnection.getURL().getQuery();
			httpResponser.ref = urlConnection.getURL().getRef();
			httpResponser.userInfo = urlConnection.getURL().getUserInfo();
			httpResponser.content = urlToString(bos.toString(ecod));
			httpResponser.data = bos.toByteArray();
			httpResponser.contentEncoding = ecod;
			httpResponser.code = urlConnection.getResponseCode();
			httpResponser.message = urlConnection.getResponseMessage();
			httpResponser.contentType = urlConnection.getContentType();
			httpResponser.method = urlConnection.getRequestMethod();
			httpResponser.connectTimeout = urlConnection.getConnectTimeout();
			httpResponser.readTimeout = urlConnection.getReadTimeout();
			return httpResponser;
		} catch (IOException e) {
			throw e;
		} finally {
			if (urlConnection != null)
				urlConnection.disconnect();
		}
	}
	/**
	 * 默认的响应字符集
	 */
	public String getDefaultContentEncoding() {
		return this.defaultContentEncoding;
	}
	/**
	 * 设置默认的响应字符集
	 */
	public void setDefaultContentEncoding(String defaultContentEncoding) {
		this.defaultContentEncoding = defaultContentEncoding;
	}
	public HttpRespons download(String urlString) throws IOException {
		HttpURLConnection urlConnection = null;
		String method = "GET";
		URL url = new URL(urlString);
		urlConnection = (HttpURLConnection) url.openConnection();
		urlConnection.setRequestMethod(method);
		urlConnection.setRequestProperty("Cookie", this.getCookie());
		urlConnection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows 2000)");
		urlConnection.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
		urlConnection.setDoOutput(true);
		urlConnection.setDoInput(true);
		urlConnection.setUseCaches(false);
		return this.makeDownload(urlString, urlConnection);
	}
	private HttpRespons makeDownload(String urlString, HttpURLConnection urlConnection) throws IOException {
		HttpRespons httpResponser = new HttpRespons();
		try {
			InputStream in = urlConnection.getInputStream();
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			httpResponser.contentCollection = new Vector<String>();
			byte[] buffer = new byte[1024 * 10];
			int total = 0;
			while ((total = in.read(buffer)) != -1) {
				bos.write(buffer, 0, total);
			}
			String ecod = urlConnection.getContentEncoding();
			if (ecod == null)
				ecod = this.defaultContentEncoding;
			httpResponser.urlString = urlString;
			httpResponser.defaultPort = urlConnection.getURL().getDefaultPort();
			httpResponser.file = urlConnection.getURL().getFile();
			httpResponser.host = urlConnection.getURL().getHost();
			httpResponser.path = urlConnection.getURL().getPath();
			httpResponser.port = urlConnection.getURL().getPort();
			httpResponser.protocol = urlConnection.getURL().getProtocol();
			httpResponser.query = urlConnection.getURL().getQuery();
			httpResponser.ref = urlConnection.getURL().getRef();
			httpResponser.userInfo = urlConnection.getURL().getUserInfo();
			httpResponser.data = bos.toByteArray();
			httpResponser.contentEncoding = ecod;
			httpResponser.code = urlConnection.getResponseCode();
			httpResponser.message = urlConnection.getResponseMessage();
			httpResponser.contentType = urlConnection.getContentType();
			httpResponser.method = urlConnection.getRequestMethod();
			httpResponser.connectTimeout = urlConnection.getConnectTimeout();
			httpResponser.readTimeout = urlConnection.getReadTimeout();
			return httpResponser;
		} catch (IOException e) {
			throw e;
		} finally {
			if (urlConnection != null)
				urlConnection.disconnect();
		}
	}
	// &#x7F51;&#x5740;,&#x8BF7;&#x76F4;&#x63A5;&#x8F93;&#x5165;&#x8981;&#x8BBF;&#x95EE;&#x7684;&#x5185;&#x5BB9;
	public static String urlToString(String source) {
		int index = 0;
		while (index != -1) {
			index = source.indexOf("&#x");
			if (index != -1) {
				int b1 = Integer.decode("0x" + source.substring(index + 3, index + 5));
				int b2 = Integer.decode("0x" + source.substring(index + 5, index + 7));
				try {
					String rep = new String(new byte[]{(byte) b1, (byte) b2}, "unicode");
					source = source.replace(source.substring(index, index + 8), rep);
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			}
		}
		return source;
	}
}